﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

using System;
using System.IO;
using System.Linq;
using ScrumTable.Common.FileSystem;

namespace ScrumTable.Common.Reflection
{
    #region Usings

    using System.Reflection;

    #endregion

    /// <summary>
    /// Contains the global utilities for the assembly class.
    /// </summary>
    public static class AssemblyUtil
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Extracts the stored resources inside the specified namespace out
        /// from the current assembly to the file system.
        /// </summary>
        /// <param name="input">Specifies the assembly which contains the resources.</param>
        /// <param name="resourceIdentificator">Specifies the identificator of the resources to extract.</param>
        /// <param name="outputPath">Specifies the file system path into which the resources should be extracted.</param>
        public static void ExtractAssemblyResources(this Assembly input, string resourceIdentificator, string outputPath)
        {
            PreCondition.AssertNotNull(input, "input");
            PreCondition.AssertNotNull(resourceIdentificator, "resourceIdentificator");
            PreCondition.AssertNotNull(outputPath, "outputPath");

            foreach (string resourceEntry in input.GetManifestResourceNames())
            {
                if (resourceEntry.Contains(resourceIdentificator))
                {
                    string[] namespaceSplit = resourceEntry.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                    string fileName = (namespaceSplit.Length > 1)
                        ? namespaceSplit[namespaceSplit.Length - 2] + "." + namespaceSplit[namespaceSplit.Length - 1]
                        : namespaceSplit[namespaceSplit.Length - 1];

                    FileInfoUtil.SaveStreamTo(
                        Path.Combine(outputPath, fileName),
                        input.GetManifestResourceStream(resourceEntry));
                }
            }
        }

        /// <summary>
        /// Extracts the stored resource with the specified name out
        /// from the current assembly to the file system.
        /// </summary>
        /// <param name="input">Specifies the assembly which contains the resources.</param>
        /// <param name="resourceIdentificator">Specifies the identificator of the resources to extract.</param>
        /// <param name="outputPath">Specifies the file system path into which the resources should be extracted.</param>
        public static void ExtractAssemblyResource(this Assembly input, string resourceIdentificator, string outputPath)
        {
            PreCondition.AssertNotNull(input, "input");
            PreCondition.AssertNotNull(resourceIdentificator, "resourceIdentificator");
            PreCondition.AssertNotNull(outputPath, "outputPath");

            var fullResourceName = (from resourceName in input.GetManifestResourceNames()
                                   where resourceName.Contains(resourceIdentificator)
                                   select resourceName).FirstOrDefault();

            if (!string.IsNullOrEmpty(fullResourceName))
            {
                FileInfoUtil.SaveStreamTo(
                    outputPath,
                    input.GetManifestResourceStream(fullResourceName));
            }
        }

        /// <summary>
        /// Gets the name of the assembly, which contains the specified type.
        /// </summary>
        /// <returns>Returns the evaluated name.</returns>
        public static string GetNameOnly(this Assembly ptr)
        {
            PreCondition.AssertNotNull(ptr, "ptr");

            string assemblyFullName = ptr.FullName;
            int indexOfComa = assemblyFullName.IndexOf(',');
            return (indexOfComa > 0) ? assemblyFullName.Substring(0, indexOfComa) : assemblyFullName;
        }

        /// <summary>
        /// Gets the description of the assembly.
        /// </summary>
        /// <returns>Returns the evaluated product name or an empty string if the assembly does not contain an AssemblyProduct attribute.</returns>
        public static string GetAssemblyDescription(this Assembly ptr)
        {
            PreCondition.AssertNotNull(ptr, "ptr");

            object[] attributes = ptr.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return ((AssemblyDescriptionAttribute)attributes[0]).Description;
            }
            return String.Empty;
        }

        /// <summary>
        /// Gets the assembly product of the assembly.
        /// </summary>
        /// <returns>Returns the evaluated product name or an empty string if the assembly does not contain an AssemblyProduct attribute.</returns>
        public static string GetAssemblyProduct(this Assembly ptr)
        {
            PreCondition.AssertNotNull(ptr, "ptr");

            object[] attributes = ptr.GetCustomAttributes(typeof(AssemblyProductAttribute), false);

            if (attributes.Length > 0)
            {
                return ((AssemblyProductAttribute) attributes[0]).Product;
            }
            return String.Empty;
        }

        /// <summary>
        /// Gets the assembly product of the given type.
        /// </summary>
        /// <returns>Returns the evaluated product name or an empty string if the assembly does not contain an AssemblyProduct attribute.</returns>
        public static string GetAssemblyProduct<T>()
        {
            return GetAssemblyProduct(typeof (T).Assembly);
        }

        #endregion
    }
}
